package com.wjerp.tplus.server.domain.service.impl;

import com.wjerp.tplus.server.api.response.ValueEnumResponse;
import com.wjerp.tplus.server.common.constant.ErrorDetail;
import com.wjerp.tplus.server.common.constant.RedisKey;
import com.wjerp.tplus.server.common.exception.BusinessException;
import com.wjerp.tplus.server.common.exception.ServiceException;
import com.wjerp.tplus.server.common.model.LoginUserDetailInfo;
import com.wjerp.tplus.server.common.model.SystemUserWrapper;
import com.wjerp.tplus.server.common.security.JwtUser;
import com.wjerp.tplus.server.common.utils.CodeGeneratorUtils;
import com.wjerp.tplus.server.common.utils.RedisUtils;
import com.wjerp.tplus.server.domain.entity.CompanyUserRelation;
import com.wjerp.tplus.server.domain.entity.sys.PermissionActionRelation;
import com.wjerp.tplus.server.domain.entity.sys.PermissionInfo;
import com.wjerp.tplus.server.domain.entity.sys.UserInfo;
import com.wjerp.tplus.server.domain.entity.sys.UserPermission;
import com.wjerp.tplus.server.domain.mapper.*;
import com.wjerp.tplus.server.domain.service.UserInfoService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lishuailei
 */
@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private UserPermissionMapper userPermissionMapper;

    @Resource
    private PermissionInfoMapper permissionInfoMapper;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private PermissionActionRelationMapper permissionActionRelationMapper;

    @Resource
    private CodeGeneratorUtils codeGeneratorUtils;

    @Resource
    private CompanyUserRelationMapper companyUserRelationMapper;

    @Override
    public List<String> findUserPermissionByDisplayUserIdAndUserType(String displayUserId, Integer userType) throws BusinessException {
        UserInfo userInfo = userInfoMapper.selectByDisplayUserId(displayUserId);
        if(userInfo == null){
            return Collections.emptyList();
        }
        List<UserPermission> userPermissions =  userPermissionMapper.selectByUserIdAndUserType(userInfo.getId(),userInfo.getUserType());
        List<String> permissions = userPermissions.stream().map(UserPermission::getPermission).distinct().collect(Collectors.toList());
        return permissions;
    }

    @Override
    public UserInfo findByMobileOrEmail(String searchKey) {
        return  userInfoMapper.selectByMobileOrEmail(searchKey);
    }

    @Override
    public UserInfo findUserInfoByDisplayUserId(String displayUserId) throws BusinessException {
        return userInfoMapper.selectByDisplayUserId(displayUserId);
    }

    @Override
    public void createSystemUser(SystemUserWrapper systemUserWrapper, JwtUser currentLoginUserInfo) throws BusinessException {
        //1、判断用户是否存在
        UserInfo userInfo= userInfoMapper.selectByMobileOrEmail(systemUserWrapper.getUserName());
        if(userInfo!=null){
            throw new BusinessException(ErrorDetail.USER_EXSITING);
        }

        //2.判断企业信息是否正确
        if(StringUtils.isEmpty(systemUserWrapper.getCompanyCode())){
            throw new BusinessException("企业编码不能为空");
        }

        //2、生成用户对象
        userInfo=new UserInfo();
        userInfo.setMobile(systemUserWrapper.getUserName());
        userInfo.setName(systemUserWrapper.getName());
        userInfo.setUserType(1);
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        userInfo.setPassword( passwordEncoder.encode(systemUserWrapper.getPassword()));
        userInfo.setCreatedTime(new Date());
        userInfo.setUpdatedTime(new Date());
        userInfo.setEnabled(true);
        userInfo.setDisplayUserId(codeGeneratorUtils.generateSysUserCode());
        Boolean result = userInfoMapper.insertSelective(userInfo) > 0;
        if(result){
            permissionInfoTransfer(userInfo,systemUserWrapper);
            createUserAndCompanyRelation(userInfo,systemUserWrapper.getCompanyCode(),currentLoginUserInfo);
        }else{
            throw new BusinessException(ErrorDetail.FAIL_CREATE_SYS_USER);
        }
    }

    /**
     * 建立用户与企业之间的关系
     * @param userInfo
     * @param companyCode
     * @param currentLoginUserInfo
     */
    private void createUserAndCompanyRelation(UserInfo userInfo, String companyCode,JwtUser currentLoginUserInfo) {
        CompanyUserRelation companyUserRelation = new CompanyUserRelation();
        companyUserRelation.setCompanyCode(companyCode);
        companyUserRelation.setUserCode(userInfo.getDisplayUserId());
        companyUserRelation.setCreatedUser(currentLoginUserInfo.getDisplayUserId());
        companyUserRelation.setUpdatedUser(currentLoginUserInfo.getDisplayUserId());
        companyUserRelation.setCreatedTime(new Date());
        companyUserRelation.setUpdatedTime(new Date());
        companyUserRelationMapper.insertSelective(companyUserRelation);
    }

    @Override
    public void updateSystemUser(Long userId, SystemUserWrapper systemUserWrapper, JwtUser currentLoginUserInfo) throws BusinessException {
        //1、判断用户是否存在
        UserInfo userInfo= userInfoMapper.selectByPrimaryKey(userId);
        if(userInfo==null){
            throw new BusinessException(ErrorDetail.USER_NOT_FOUND);
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if(systemUserWrapper.getName()!=null){
            userInfo.setName(systemUserWrapper.getName());
        }

        if(systemUserWrapper.getPassword()!=null){
            userInfo.setPassword(passwordEncoder.encode(systemUserWrapper.getPassword()));
        }
        Boolean result= userInfoMapper.updateByPrimaryKeySelective(userInfo) > 0;
        if(!result){
            throw new BusinessException(ErrorDetail.FAIL_EDIT_USER);
        }
        permissionInfoTransfer(userInfo,systemUserWrapper);
    }

    @Override
    public void resetUserPassword(String displayUserId) throws BusinessException {
        //1、判断用户是否存在
        UserInfo userInfo = findUserInfoByDisplayUserId(displayUserId);
        if(userInfo==null){
            throw new BusinessException(ErrorDetail.USER_NOT_FOUND);
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        userInfo.setPassword(passwordEncoder.encode("123456"));
        Boolean result= userInfoMapper.updateByPrimaryKeySelective(userInfo) > 0;
        if(!result){
            throw new BusinessException(ErrorDetail.FAIL_RESET_USER_PWD);
        }
    }

    @Override
    public Map<String, Object> findSystemUserListByPage(String name, String userName, Boolean status, String startDate, String endDate, Integer page, Integer size, int i) {
        if(!endDate.isEmpty()){
            endDate=endDate.split(" ")[0]+" 23:59:59";
        }else{
            SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            endDate= simpleDateFormat.format(new Date());
        }

        Integer allStatus=0;

        if(null==status){
            allStatus=1;
        }

        //查询符合条件的数据
        List<UserInfo> userInfos= userInfoMapper.findUserInfoListPage("%"+name+"%","%"+userName+"%",status,allStatus,1, startDate,endDate, (page-1)*size,size);
        //获取符合条件的记录总数
        Integer totalCount=userInfoMapper.findUserInfoListPageCount("%"+name+"%","%"+userName+"%",status,allStatus,1, startDate,endDate );

        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("total",totalCount);
        resultMap.put("datas",userInfos);
        return resultMap;
    }

    @Override
    public void updateUserStatus(String displayUserId, boolean status) throws BusinessException {
        try {
            UserInfo userInfo = userInfoMapper.selectByDisplayUserId(displayUserId);
            userInfo.setEnabled(status);
            userInfoMapper.updateByPrimaryKeySelective(userInfo);
            Set<String> keySet = redisUtils.keys(RedisKey.LOGIN_USER_TOKEN+displayUserId+"*");
            keySet.stream().forEach(p -> redisUtils.remove(p));
        }catch (Exception ex){
            ex.printStackTrace();
            throw new BusinessException(ErrorDetail.MODIFY_USER_STATUS_FAIL);
        }
    }

    @Override
    public void modifyPassword(String displayUserId, String password) throws BusinessException {
        //1、判断用户是否存在
        UserInfo userInfo = findUserInfoByDisplayUserId(displayUserId);
        if(userInfo==null){
            throw new BusinessException(ErrorDetail.USER_NOT_FOUND);
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        userInfo.setPassword(passwordEncoder.encode(password));
        Boolean result= userInfoMapper.updateByPrimaryKeySelective(userInfo) > 0;
        if(!result){
            throw new BusinessException(ErrorDetail.FAIL_RESET_USER_PWD);
        }
    }

    @Override
    public void distributionPermissionByUser(Long userId, List<UserPermission> userPermissions) throws BusinessException {
        //1、判断用户是否存在
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(userId);
        if(userInfo==null){
            throw new BusinessException(ErrorDetail.USER_NOT_FOUND);
        }
        //2、删除已经存在的分配权限信息
        userPermissionMapper.deleteByUserId(userId);
        for(UserPermission data:userPermissions){
            data.setUserId(userId);
            data.setUserType(userInfo.getUserType().equals(2)?2:1);
            if(data.getPermission()==null || data.getPermission().isEmpty()){
                continue;
            }
            userPermissionMapper.insertSelective(data);
        }
    }

    @Override
    public List<PermissionActionRelation> findAllPermissionActionRelation() {
        return permissionActionRelationMapper.selectAll();
    }

    private void permissionInfoTransfer(UserInfo userInfo, SystemUserWrapper systemUserWrapper) throws BusinessException {
        //分配权限
        List<Long> permissionIdArr=systemUserWrapper.getPermissionIds();
        //获取权限信息
        List<PermissionInfo> permissionInfoList= permissionInfoMapper.selectAll();
        List<UserPermission> userPermissions=new ArrayList<>();

        for (Long aLong : permissionIdArr) {
            List<PermissionInfo> temp = permissionInfoList.stream().filter(p -> p.getId().equals(aLong)).collect(Collectors.toList());
            if (temp.size() == 0) {
                continue;
            }
            UserPermission userPermission = new UserPermission();
            userPermission.setUserId(userInfo.getId());
            userPermission.setPermission(temp.get(0).getName());
            userPermission.setUserType(userInfo.getUserType().intValue() == 2 ? 2 : 1);
            userPermissions.add(userPermission);
        }

        distributionPermissionByUser(userInfo.getId(),userPermissions);
    }

    @Override
    public LoginUserDetailInfo getUserDetailInfo(String displayUserId) throws BusinessException {
        UserInfo userInfo = userInfoMapper.selectByDisplayUserId(displayUserId);
        LoginUserDetailInfo loginUserDetailInfo = new LoginUserDetailInfo();
        loginUserDetailInfo.setEmail(userInfo.getEmail());
        loginUserDetailInfo.setMobile(userInfo.getMobile());
        loginUserDetailInfo.setEnabled(userInfo.getEnabled());
        // UserDetailInfo userDetailInfo = userInfoDao.getUserDetailInfo(userInfo.getId());
        loginUserDetailInfo.setName(userInfo.getName());
        loginUserDetailInfo.setDisplayUserId(userInfo.getDisplayUserId());
        loginUserDetailInfo.setUserType(userInfo.getUserType());
        return loginUserDetailInfo;
    }

    @Override
    public List<UserInfo> findUserInfoByDisplayUserIds(List<String> displayUserIdList){
        if(CollectionUtils.isEmpty(displayUserIdList)){
            return Collections.emptyList();
        }
        return userInfoMapper.selectByDisplayUserIds(displayUserIdList);
    }

    @Override
    public List<ValueEnumResponse> findAllUserInfoList() {
        List<UserInfo> userInfos = userInfoMapper.selectAll();
        if(CollectionUtils.isEmpty(userInfos)){
            return Collections.emptyList();
        }
        List<ValueEnumResponse> valueEnumResponseList = new ArrayList<>();
        userInfos.stream().forEach(data->{
            ValueEnumResponse valueEnumResponse = new ValueEnumResponse(data.getName(),data.getDisplayUserId());
            valueEnumResponseList.add(valueEnumResponse);
        });
        return valueEnumResponseList;
    }
}
